#include "GameState.h"
#include "Game.h"
#include "Level.h"
#include "Item.h"
#include "Obstacle.h"
#include "Player.h"
#include "Npc.h"
#include "Corpse.h"

GameState::GameState() {
	m_playersTurn = true;
	m_playerTookTurn = false;
}

GameState::~GameState() {
	cleanUp();
}

void GameState::updateCharacterList() {
	m_characters.clear();
	m_characters.push_back(g_player);
	for(std::list<Npc*>::iterator iter = g_currentLevel->getNpcs()->begin(); iter != g_currentLevel->getNpcs()->end(); iter++) {
		insertionSort(*iter);
	}
}

void GameState::insertionSort(Character* c) {
	std::list<Character*>::reverse_iterator iter = m_characters.rbegin();
	bool found = false;
	for(; iter != m_characters.rend(); iter++) {
		if((*iter)->getTurnCounter() < c->getTurnCounter()) {
			found = true;
			break;
		}
	}
	if(!found)
		m_characters.push_front(c);
	else if(iter == m_characters.rbegin())
		m_characters.push_back(c);
	else
		m_characters.insert(iter.base(), c);
}

void GameState::resolveTurns() {
	while((*(m_characters.begin()))->getTurnCounter() < 0 && m_playersTurn == false) {
		if((*(m_characters.begin()))->getType(TH_GENERIC_TYPE) == GT_CH_PLAYER) {
			m_playersTurn = true;
		} else {
			Npc* n = ((Npc*)(*(m_characters.begin())));
			n->takeTurn();
			if(g_gameMode.top() == GM_DEAD) {
				m_playersTurn = true;
				return;
			}
			if(n->getHealthStatus() != HS_DEAD) {
				m_characters.remove(n);
				insertionSort(n);
			}
		}
		cleanUp();
	}
}

void GameState::takeTurns() {
	while(m_playersTurn == false) {
		for(std::list<Character*>::iterator iter = m_characters.begin(); iter != m_characters.end(); iter++) {
			(*iter)->modifyTurnCounter(-DEFAULT_TURN_LENGTH);
			if(g_gameMode.top() == GM_DEAD) {
				m_playersTurn = true;
				return;
			}
		}
		std::list<Corpse*> corpsesToRemove;
		for(std::list<Corpse*>::iterator iter = m_corpses.begin(); iter != m_corpses.end(); iter++) {
			if((*iter)->reduceRotCounter())
				corpsesToRemove.push_back(*iter);
		}
		for(std::list<Corpse*>::iterator iter = corpsesToRemove.begin(); iter != corpsesToRemove.end(); iter++) {
			m_corpses.remove(*iter);
			markForDeletion(*iter);
		}
		cleanUp();
		resolveTurns();
	}
}

void GameState::playerTookTurn() {
	if(g_gameMode.top() == GM_DEAD) return;
	cleanUp();
	m_playersTurn = false;
	m_characters.remove(g_player);
	insertionSort(g_player);
	resolveTurns();
	takeTurns();
}

void GameState::markPlayerTookTurn() {
	m_playerTookTurn = true;
}

void GameState::checkPlayerTookTurn() {
	if(m_playerTookTurn) {
		m_playerTookTurn = false;
		playerTookTurn();
	}
}

void GameState::removeCharacter(Character* c) {
	m_characters.remove(c);
}

void GameState::addCharacter(Character* c) {
	insertionSort(c);
}

void GameState::removeCorpse(Corpse* c) {
	m_corpses.remove(c);
}

void GameState::addCorpse(Corpse* c) {
	m_corpses.push_back(c);
}

void GameState::markForDeletion(Character* c) {
	m_deadCharacters.push_back(c);
}

void GameState::markForDeletion(Item* item) {
	m_destroyedItems.push_back(item);
}

void GameState::markForDeletion(Obstacle* o) {
	m_destroyedObstacles.push_back(o);
}

void GameState::cleanUp() {
	while(m_deadCharacters.size() > 0) {
		Character *c = *(m_deadCharacters.begin());
		removeCharacter(c);
		m_deadCharacters.remove(c);
		delete c;
	}
	while(m_destroyedItems.size() > 0) {
		Item* i = *(m_destroyedItems.begin());
		if(i->getParentList() != NULL)
			i->getParentList()->remove(i);
		m_destroyedItems.remove(i);
		delete i;
	}
	while(m_destroyedObstacles.size() > 0) {
		Obstacle* o = *(m_destroyedObstacles.begin());
		m_destroyedObstacles.remove(o);
		delete o;
	}
}